# -*- coding:utf-8
import zmq
import configparser
import time
import os
import re
import json
import threading
import sys
import traceback
import zipfile
import shutil
from update.tools.w_update_send import EchoHandler
from socketserver import BaseRequestHandler, TCPServer, ThreadingTCPServer

class server_cu(object):
    def __init__(self):
        self.context = zmq.Context()
        # self.config_file = r'update\tools\config.ini'
        # self.Equipment_file = r'update\tools\Equipment.ini'
        self.config_file = r'D:\pycharms\django\operationsb\update\tools\config.ini'
        self.Equipment_file = r'D:\pycharms\django\operationsb\update\tools\Equipment.ini'
        self.Equipment = configparser.ConfigParser()
        self.Equipment.read(self.Equipment_file)
        self.config = configparser.ConfigParser()
        self.config.read(self.config_file)
        self.updata_status = True
        self.send_status = True

    def pub_zcell_all(self,zcell_list, zcell_rules):
        #开启发布模式
        pub_socket = self.context.socket(zmq.PUB)
        pub_port = self.config.get('ports','up_pub_port')
        pub_socket.bind("tcp://*:%s" % pub_port)
        sleep_time = 1
        while self.updata_status:
            time.sleep(sleep_time)
            for i in zcell_list:
                msg = i + "|" + zcell_rules
                print("发送的->", msg)
                pub_socket.send_string(msg)
            sleep_time += 1

    def pub_zcell_one(self,zcell_list):
        pub_socket = self.context.socket(zmq.PUB)
        pub_port = self.config.get('ports','up_pub_port')
        pub_socket.bind("tcp://*:%s" % pub_port)
        sleep_time = 1
        while self.updata_status:
            time.sleep(sleep_time)
            try:
                for i in zcell_list:
                    msg = i["id"] + "|" + str(i["module"]) + "|"
                    print("->", msg)
                    pub_socket.send_string(msg)
                sleep_time += 1
            except BaseException as b:
                traceback.print_exc()
                # 打印异常（简单）
                print("程序异常，关闭发布模式")
                self.updata_status = False
    
    def rep_zcell(self, zcell_list):
        rep_port = self.config.get('ports', 'up_rep_port')
        rep_socket = self.context.socket(zmq.REP)
        rep_socket.bind("tcp://*:%s" % rep_port)
        #计时器
        poll = zmq.Poller()
        poll.register(rep_socket, zmq.POLLIN)
        global zcell_json_list
        zcell_json_list = []
        n = 0
        while self.updata_status:
            try:
                socks = dict(poll.poll(60000))
                if socks.get(rep_socket) == zmq.POLLIN:
                    msg = rep_socket.recv_string()
                    if msg == 'one':
                        #指定更新
                        zcell_json_list = zcell_list
                        n += 1
                        rep_socket.send_string('开始更新了')
                        if len(zcell_list) == n:
                            zcell_json_list = zcell_list
                            self.updata_status = False
                    else:
                        #全部更新
                        msg_json = json.loads(msg)
                        print(msg)
                        try:
                            zcell_json_list.index(msg_json)
                        except:
                            zcell_json_list.append(msg_json)
                        rep_socket.send_string('开始更新了')
                        if len(zcell_json_list) == len(zcell_list):
                            self.updata_status = False
                else:
                    found_zcell_list = [item["id"] for item in zcell_json_list]
                    ret_list = [item for item in zcell_list if item not in found_zcell_list]
                    print(ret_list,'以上主机连接超时！')
                    self.updata_status = False
            except BaseException as b:
                #打印异常（详情）
                traceback.print_exc()
                # 打印异常（简单）
                print("程序异常，关闭所有连接")
                self.updata_status = False
    
    def updata_file(self):
        module_name = []
        module_rules = []
        updata_file=self.config.get('service_side','updata_file')
        list1 = os.listdir(updata_file)
        for iterm in list1:
            updata1 = updata_file + '\\' + iterm
            if len(os.listdir(updata1)) != 0:
                name = self.Equipment.get("Equipment1", iterm)
                name_zip = name + '.zip'
                updata2 = updata_file + '\\' + name_zip
                self.start_zip(updata1, updata2)
                list2 = os.listdir(updata1)
                if name_zip in list2:
                    module_name.append(name)
                    module_rules.append(re.compile(r'%s' % name))
        print(module_name, module_rules)
        return module_rules, module_name

    def start_zip(self, f1, f2):
        try:
            pre_len = len(f1)
            zipf = zipfile.ZipFile(f2, 'w')
            for parent, dirnames, filenames in os.walk(f1):
                for filename in filenames:
                    pathfile = os.path.join(parent, filename)
                    arcname = pathfile[pre_len:].strip(os.path.sep)
                    zipf.write(pathfile, arcname, compress_type=zipfile.ZIP_DEFLATED)
            zipf.close()
            shutil.move(f2, f1)
        except BaseException as b:
            _log_err = "start_zip 函数异常 --》" + str(b)
            print(_log_err)
            # os._exit(2)
            sys.exit(2)
    
    def start_zip_thread(self):
        #thread_port = self.config.get('ports', 'thread_logo_1')
        updata_list = []
        for i in zcell_json_list:
            updata_list.append(i["id"])
        print("更新列表：", updata_list)
        already_updata_list = []
        thread_socket_host = self.config.get('ports', 'thread_up_host')
        thread_socket_post1 = self.config.get('ports', 'thread_up_rep1_port')
        thread_socket_post2 = self.config.get('ports', 'thread_up_rep2_port')
        initial_date = time.mktime(time.localtime())
        timeout = initial_date + 180
        while self.send_status:
            if timeout < time.mktime(time.localtime()):
                print('等待超时！')
                serv.shutdown()
                self.send_status = False
                # os._exit(1)
                sys.exit(1)
            if updata_list != []:
                print('开始接受消息')
                timeout += 60
                thread_socket = self.context.socket(zmq.REP)
                thread_socket.bind("tcp://%s:%s" % (thread_socket_host, thread_socket_post1))
                con_ip = thread_socket.recv_string()
                print(con_ip,'=================1')
                thread_status = 0
                # for i in zcell_json_list:
                #     updata_list.append(i["id"])
                #     if i["ip"] == con_ip:
                #         send_thread_data = json.dumps(zcell_json_list)
                #         thread_socket.send_string(send_thread_data)
                #         print('告知server端发送数据包线程')
                send_thread_data = json.dumps(zcell_json_list)
                thread_socket.send_string(send_thread_data)
                print('告知server端发送数据包线程')
                thread_socket.close()
                thread_socket_2 = self.context.socket(zmq.REP)
                thread_socket_2.bind("tcp://%s:%s" % (thread_socket_host, thread_socket_post2))
                status = thread_socket_2.recv_string()

                thread_socket_2.close()

                if status == "error":
                    print('无法匹配到对应的模块名称，程序结束')
                    serv.shutdown()
                    self.send_status = False
                    # os._exit(1)
                    sys.exit(1)
                print(status, '已经更新完成！')
                already_updata_list.append(status)
                not_updated_list = [item for item in updata_list if item not in already_updata_list]
                if len(not_updated_list) == 0:
                    print('关闭所有线程')
                    serv.shutdown()
                    self.send_status = False
                    os._exit(0)
                else:
                    print('=================3')
                    print(updata_list)
                    print(already_updata_list)
                
    
    def start_zip_send(self):
        #NWORKERS = 1
        socket_post = int(self.config.get('update','socket_port'))
        global serv
        serv = TCPServer(('', socket_post), EchoHandler)
        #for n in range(NWORKERS):
        t = threading.Thread(target=serv.serve_forever)
        #t.daemon = True
        t.start()
        print('=================1')
        serv.serve_forever(poll_interval=0.5)
        print('=======================')
        
    
    def main_body(self,name,status):
        ##################
        ##全部更新：根据更新包存放的目录文件来判断需要更新的模块，状态为：1
        ##选择更新：根据选择更新模块，状态为：2
        ##t3线程是开socket连接
        ##t1线程是开启发布模式，通知相关订阅者开始发起对话
        ##################
        update_status = status
        if update_status == 1:
            zcell_list = name
            zcell_rules, zcell_name = self.updata_file()
            t3 = threading.Thread(target=self.start_zip_send)
            t3.start()
            t1 = threading.Thread(target=self.pub_zcell_all, args=(zcell_list, repr(zcell_rules),))
            t2 = threading.Thread(target=self.rep_zcell, args=(zcell_list,))
            t4 = threading.Thread(target=self.start_zip_thread)
            t1.start()
            t2.start()
            t1.join()
            t2.join()
            t4.start()
        elif update_status == 2:
            zcell_list = name
            self.updata_file()
            t3 = threading.Thread(target=self.start_zip_send)
            t3.start()
            t1 = threading.Thread(target=self.pub_zcell_one, args=(zcell_list,))
            t2 = threading.Thread(target=self.rep_zcell, args=(zcell_list,))
            t4 = threading.Thread(target=self.start_zip_thread)
            t1.start()
            t2.start()
            t1.join()
            t2.join()
            t4.start()
        else:
            print("更新类型出错，值不是1或2")
        
if __name__ == '__main__':
    a = server_cu()
    # a.start_zip_send()
    # a.main_body(["zcell01", "zcell02"],1)
    # a .main_body([{"id": "zcell02", "module": ["KLX0300202"], "number": 1, "ip": "192.168.1.104"}], 2)
    try:
        b = threading.Thread(target=a.main_body, args=([{"id": "zcell02", "module": ["KLX0300202"], "number": 1, "ip": "192.168.1.104"}], 2,))
        b.start()
        b.join()
        print()
    except SystemExit as b:
        print(111111)
    # pid, status = os.waitpid(b, 0)
    # thread_list = threading.enumerate()
    # for ct_i in thread_list:
    #     print(ct_i)
    #     pid, status = os.waitpid(ct_i.id, 0)
    #     exit_code = os.WEXITSTATUS(status)
    #     print(exit_code)
    # try:
    #     a.main_body([{"id": "zcell02", "module": ["KLX0300202"], "number": 1, "ip": "192.168.1.104"}], 2)
    # except :
    #     pass
    # finally:
    #     print("!!!!!!!!!!!!!!!!!!")